from rest_framework import serializers
from .models import Server,Cloud,Ip
import logging
logger = logging.getLogger(__name__)

class ServerSerializer(serializers.Serializer):
    id             = serializers.ReadOnlyField()
    # 关联验证，many单数据对应验证
    cloud          = serializers.PrimaryKeyRelatedField(queryset=Cloud.objects.all(),many=False)
    instanceId     = serializers.CharField(required=True)
    instanceType   = serializers.CharField(required=True)
    cpu            = serializers.CharField(required=True)
    memory         = serializers.CharField(required=True)
    instanceName   = serializers.CharField(required=True)
    createTime     = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S",required=True)   #时间格式定义
    expiredTime    = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S",required=True)
    osname         = serializers.CharField(required=True)
    innerIps       = serializers.ListField(required=True,write_only=True)        #单独加入的类型需要另外加write_only
    publicIps      = serializers.ListField(required=True,write_only=True)


    class Meta:
        model = Server
        fields = "__all__"

    def getCloudPK(self,code):
        # 获取Cloud（云厂商）的主键
        try:
            obj = Cloud.objects.get(code__exact=code)
            return obj.id
        except Cloud.DoesNotExist:
            logger.error("云厂商:{} 不存在".format(code))
            raise serializers.ValidationError("云厂商不存在")
        except Exception as e:
            logger.error("云厂商错误：".format(e.args))
            raise serializers.ValidationError("云厂商错误")

    def to_internal_value(self, data):
        # 返回序列化接收到的字段
        data['cloud'] = self.getCloudPK(data['cloud'])
        print("to_internal_value", data)
        return super(ServerSerializer, self).to_internal_value(data)

    def getInstance(self,instanceId):
        # 获取实例ID
        try:
            return Server.objects.get(instanceId__exact=instanceId)
        except Server.DoesNotExist:
            return None
        except Exception as e:
            logger.error("服务器其他错误：{}".format(e.args))
            raise serializers.ValidationError("服务器其他错误")

    def create(self, validated_data):
        #创建和更新数据
        instance = self.getInstance(validated_data["instanceId"])
        if instance is not None:
            return self.update(instance,validated_data)
        innerIps = validated_data.pop('innerIps')
        publicIps = validated_data.pop('publicIps')
        instance = Server.objects.create(**validated_data)
        self.check_inner_ip(instance,innerIps)
        self.check_public_ip(instance,publicIps)
        return instance

    def update(self, instance, validated_data):
        #更新数据，create必须调用
        instance.cpu = validated_data.get("cpu","")
        self.check_inner_ip(instance, validated_data['innerIps'])
        self.check_public_ip(instance, validated_data['publicIps'])
        return instance

    def check_inner_ip(self, instance, innerIps):
        #inner_ip字段校验与更新
        ip_queryset = instance.innerIpAddress.all()
        current_ip_objs = []
        for ip in innerIps:
            try:
                ip_obj = ip_queryset.get(ip__exact=ip)
            except Ip.DoesNotExist:
                ip_obj = Ip.objects.create(ip=ip, inner=instance)
            current_ip_objs.append(ip_obj)
        self.cleanip(ip_queryset, current_ip_objs)

    def check_public_ip(self, instance, publicIps):
        #public_ip校验与更新
        ip_queryset = instance.publicIpAddress.all()
        current_ip_objs = []
        for ip in publicIps:
            try:
                ip_obj = ip_queryset.get(ip__exact=ip)
            except Ip.DoesNotExist:
                ip_obj = Ip.objects.create(ip=ip, public=instance)
            current_ip_objs.append(ip_obj)
        self.cleanip(ip_queryset, current_ip_objs)

    def cleanip(self, ip_queryset, current_ip_objs):
        # 清理旧的IP数据
        not_exists_ip = set(ip_queryset) - set(current_ip_objs)
        for obj in not_exists_ip:
            obj.delete()

    def to_representation(self, instance):
        # 处理页面展示数据
        ret = super(ServerSerializer, self).to_representation(instance)
        ret["cloud"] = {
            "id": instance.cloud.id,
            "name": instance.cloud.name
        }
        ret['publicIps'] = [public_ip.ip for public_ip in instance.publicIpAddress.all()]
        ret['innerIps'] = [inner_ip.ip for inner_ip in instance.innerIpAddress.all()]
        # for public_ip in instance.publicIpAddress.all():
        #     ret['publicIps'].append(public_ip.ip)
        # for inner_ip in instance.innerIpAddress.all():
        #     ret['innerIps'].append(inner_ip.ip)
        return ret